function amguirack
%SMGUIRACK Summary of this function goes here
%   Detailed explanation goes here

%% setup
global amrack amscan amaux;
ampath=strrep(mfilename('fullpath'),'amguirack','');
inststruct=dir([ampath '\instruments\*.m']);
hdata.instfiles=cellfun(@(x)x(4:end-2),{inststruct.name},'UniformOutput',0);
hdata.fighand=figure(234);
set(hdata.fighand,'Name','Automeasure Rack','NumberTitle','off','MenuBar','none','Toolbar','none')
hdata.instparent=uipanel('Title','Instruments','Position',[0,0,2/5,1]);
hdata.chanparent=uipanel('Title','Channels','Position',[2/5,0,3/5,1]);
hdata.instpage=1; hdata.rcpage=1; hdata.instpanel=[]; hdata.rcpanel=[];
%set up the figure menu
filemenu=uimenu('Label','File');
uimenu(filemenu,'Label','Save Rack','Callback',@saverack); uimenu(filemenu,'Label','Open Rack','Callback',@loadrack);
editmenu=uimenu('Label','Edit');
uimenu(editmenu,'Label','Add Instrument','Callback',@addinst); uimenu(editmenu,'Label','Add Rack Channel','Callback',@addrc);

guidata(hdata.fighand,hdata);
refreshinst(hdata.fighand);
refreshrc(hdata.fighand);
end
%% refresh instruments
function refreshinst(fighand)
hdata=guidata(fighand);
global amrack;
delete(get(hdata.instparent,'Children'));
clear('hdata.inst');
for i=1:length(amrack.insts)
    hdata.inst(i).panel=uipanel('Parent',hdata.instparent,'Title',num2str(i),'Position',[0,1-0.1*i,1,0.1]);
    instprops={'Parent',hdata.inst(i).panel,'units','normalized','HorizontalAlignment','left'};
    hdata.inst(i).name=uicontrol(instprops{:},'Style','popupmenu','Position',[0,0,0.4,1],'String',hdata.instfiles,'Value',find(strcmp(amrack.insts(i).instname,hdata.instfiles)),'Callback',{@editinst,i,'instname'});
    hdata.inst(i).rackname=uicontrol(instprops{:},'Style','edit','Position',[0.4,0,0.4,1],'String',amrack.insts(i).rackname,'Callback',{@editinst,i,'rackname'});
    hdata.inst(i).address=uicontrol(instprops{:},'Style','edit','Position',[0.8,0,0.1,1],'String',amrack.insts(i).address,'Callback',{@editinst,i,'address'});
    hdata.inst(i).del=uicontrol(instprops{:},'Style','pushbutton','BackgroundColor','Red','Position',[0.95,0,0.05,1],'String','X','Callback',{@removeinst,i});
end
end
%% refresh rack channels
function refreshrc(fighand)
hdata=guidata(fighand);
global amrack;
delete(get(hdata.chanparent,'Children'));
clear('hdata.rc');
for i=1:length(amrack.rackchans)
    hdata.rc(i).panel=uipanel('Parent',hdata.chanparent,'Title',num2str(i),'Position',[0,1-0.1*i,1,0.1]);
    rcprops={'Parent',hdata.rc(i).panel,'units','normalized','HorizontalAlignment','left'};
    hdata.rc(i).name=uicontrol(rcprops{:},'Style','edit','Position',[0,0,0.1,1],'String',amrack.rackchans(i).name,'Callback',{@editrc,i,'name'});
    hdata.rc(i).inst=uicontrol(rcprops{:},'Style','popupmenu','Position',[0.1,0,0.2,1],'String',amrack.insts.fullname,'Value',find(amrack.insts==amrack.rackchans(i).inst),'Callback',{@editrc,i,'inst'});
    hdata.rc(i).chan=uicontrol(rcprops{:},'Style','popupmenu','Position',[0.3,0,0.15,1],'String',{amrack.rackchans(i).inst.channels.name},'Value',find(amrack.rackchans(i).inst.channels==amrack.rackchans(i).channel),'Callback',{@editrc,i,'channel'});
    hdata.rc(i).min=uicontrol(rcprops{:},'Style','edit','Position',[0.45,0,0.1,1],'String',num2str(amrack.rackchans(i).min),'Callback',{@editrc,i,'min'});
    hdata.rc(i).max=uicontrol(rcprops{:},'Style','edit','Position',[0.55,0,0.1,1],'String',num2str(amrack.rackchans(i).max),'Callback',{@editrc,i,'max'});
    hdata.rc(i).maxrate=uicontrol(rcprops{:},'Style','edit','Position',[0.65,0,0.1,1],'String',num2str(amrack.rackchans(i).maxrate),'Callback',{@editrc,i,'maxrate'});
    hdata.rc(i).mult=uicontrol(rcprops{:},'Style','edit','Position',[0.75,0,0.1,1],'String',num2str(amrack.rackchans(i).multiplier),'Callback',{@editrc,i,'multiplier'});
    hdata.rc(i).const=uicontrol(rcprops{:},'Style','edit','Position',[0.85,0,0.1,1],'String',num2str(amrack.rackchans(i).const),'Callback',{@editrc,i,'const'});
    hdata.rc(i).del=uicontrol(rcprops{:},'Style','pushbutton','BackgroundColor','Red','Position',[0.95,0,0.05,1],'String','X','Callback',{@removerc,i});
end
guidata(hdata.fighand,hdata);
end
%% edit callback for the rack channel fields
function editrc(hObject,eventdata,num,field) %num is rackchan index, field is the edited field
global amrack;
switch field
    case {'min','max','multiplier','constant'}
        val=get(hObject,'String');
        if isnumeric(str2double(val))
            amrack.rackchans(num).(field)=val;
        else
            errordlg('Input must be a number','Error');
            set(hObject,'String',num2str(amrack.rackchans(num).(field)));
        end
    case {'name'}
        set(hObject,'String',genvarname(get(hObject,'String'),{amrack.rackchans.name})); %make sure name is unique, ok for a field
        amrack.rackchans(num).(field)=get(hObject,'String');
    case {'maxrate'}
        val=get(hObject,'String');
        if isnumeric(str2double(val)) && str2double(val)>0 % rate must be positive number
            amrack.rackchans(num).(field)=val;
        else
            errordlg('Input must be a positive number','Error');
            set(hObject,'String',num2str(amrack.rackchans(num).(field)));
        end
    case {'channel'}
        amrack.rackchans(num).(field)=amrack.rackchans(num).inst.channels(get(hObject,'Value'));
    case {'inst'}
        hdata=guidata(hObject);
        set(hdata.rc(num).chan,'Value',1,'String',{amrack.insts(get(hObject,'Value')).channels.name});
        amrack.rackchans(num).channel=amrack.insts(get(hObject,'Value')).channels(1);
end
end
%% edit callback for the instrument fields
function editinst(hObject,eventdata,num,field)
global amrack;
hdata=guidata(hObject);
switch field
    case {'rackname'}
        set(hObject,'String',genvarname(get(hObject,'String'))); %make sure name is ok for a field
        amrack.insts(num).(field)=get(hObject,'String');
        refreshrc(hdata.fighand);
    case {'address'}
        amrack.insts(num).setaddress(get(hObject,'String')); 
    case {'instname'}
        oldname=amrack.insts(num).rackname;
        oldaddr=amrack.insts(num).address;
        newfn=str2func(['ami' hdata.instfiles{get(hObject,'Value')}]);
        delete(amrack.insts(num)); %destructor takes care of all linked data
        %now add new inst back in where where old one was
        amrack.insts(num+1:end+1)=amrack.insts(num:end);
        amrack.insts(num)=feval(newfn,oldname,oldaddr);

        refreshinst(hdata.fighand);
        refreshrc(hdata.fighand);
end
end
%% add new rack channel
function addrc(hObject,eventdata)
global amrack;
hdata=guidata(hObject);
%###set page to last
amrack.rackchans(end+1)=amcrackchan(genvarname('New',{amrack.rackchans.name}),amrack.insts(1).channels(1));
refreshrc(hdata.fighand);
end
%% add new instrument
function addinst(hObject,eventdata)
global amrack;
hdata=guidata(hObject);
%###set page to last
amrack.insts(end+1)=feval(str2func(['ami' hdata.instfiles{1}]),'0','');
refreshinst(hdata.fighand);
end
%% delete rack channel
function removerc(hObject,eventdata,num)
global amrack;
hdata=guidata(hObject);
delete(amrack.rackchans(num));
refreshrc(hdata.fighand);
end
%% delete instrument
function removeinst(hObject,eventdata,num)
global amrack;
hdata=guidata(hObject);
delete(amrack.insts(num));
refreshinst(hdata.fighand);
refreshrc(hdata.fighand);
end
%% save rack
function saverack(hObject,eventdata)
global amrack;
uisave('amrack','rack'); %change this to uiputfile+save
end
%% load rack
function loadrack(hObject,eventdata)
global amrack;
hdata=guidata(hObject);
uiopen('LOAD'); %change this to uigetfile+load
refreshinst(hdata.fighand);
refreshrc(hdata.fighand);
end
